package com.sky.aspect;

import com.sky.constant.AutoFillConstant;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import com.sky.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自定义切面类: 用来自动填充公共字段
 */
@Component
@Aspect
@Slf4j
public class AutoFillAspect {

    /**
     * 公共字段字段填充
     * @param joinPoint
     */
    @Before("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.aspect.AutoFill)")
    public void autoFill(JoinPoint joinPoint){
        // 获取到切入点（增强的方法）
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        log.info("方法名：{}", methodSignature.getName());
        Method method = methodSignature.getMethod();    //方法对象

        // 获取方法上面的注解
        AutoFill autoFill = method.getAnnotation(AutoFill.class);

        // 判断方法上面注解的属性
        OperationType value = autoFill.value();

        // 定义待补充的参数值
        LocalDateTime now = LocalDateTime.now();        //系统时间
        Long currentId = BaseContext.getCurrentId();    //登录人id

        // 获取连接点对象的形参
        Object[] args = joinPoint.getArgs();
        Object entity = args[0];

        if (value.equals(OperationType.INSERT)) {
            // 如果属性是新增，应该补充4个字段
            // 通过连接点对象获取方法中的参数对象  eg：employee
            //获取到实体对象，调用set方法      （通过反射）
            try {
                //通过反射获取方法对象
                Method createTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method updateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method createUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method updateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //调用方法
                createTime.invoke(entity, now);
                updateTime.invoke(entity, now);
                createUser.invoke(entity, currentId);
                updateUser.invoke(entity, currentId);
            } catch (Exception e) {
                log.error("公共字段自动填充失败, {}", e.getMessage());
                throw new BaseException(MessageConstant.AUTO_FILL_FAILED);
            }
        }else {
            // 如果属性是更新，应该补充2个字段
            //获取到实体对象，调用set方法      （通过反射）
            try {
                //通过反射获取方法对象
                Method updateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method updateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //调用方法
                updateTime.invoke(entity, now);
                updateUser.invoke(entity, currentId);
            } catch (Exception e) {
                log.error("公共字段自动填充失败, {}", e.getMessage());
                throw new BaseException(MessageConstant.AUTO_FILL_FAILED);
            }
        }

    }
}
